from numpy import (
    ndarray,  # 数组类型
    arange,  # 创建等差数组
    exp,  # 自然指数函数
    pi,  # 圆周率常量
)


def los_channel_error_model_multiplicative_on_cos(
        error_model_config,  # 错误模型配置对象，包含误差的相关参数
        satellite,  # 卫星对象
        users: list,  # 用户列表，每个用户表示一个通信用户
) -> ndarray:
    """
    视距（LOS）信道的误差模型，其中误差乘法地作用在卫星天线方向图上。
    注意：如果卫星的天线数量为奇数，那么中间天线的误差始终为零，学习算法可以利用这个特性忽略该误差。

    参数:
    - error_model_config: 错误模型配置参数，定义误差区间
    - satellite: 卫星对象，包含信道状态、天线数量、天线距离、波长等属性
    - users: 用户对象列表

    返回:
    - ndarray: 包含误差信道状态信息的数组
    
    详细说明:
    - 该函数为视距信道模型添加了一个乘法误差，该误差作用在卫星的天线方向图上。
    - 误差是在天线索引处添加的，通过指数函数（`exp`）来模拟相位误差的影响。
    """

    # 计算天线方向图索引，中心天线索引为 0，左右天线分别为负数和正数
    steering_idx = arange(0, satellite.antenna_nr) - (satellite.antenna_nr - 1) / 2

    # 根据误差模型配置生成一个与用户数量相匹配的误差因子
    # 错误因子基于均匀分布的随机误差范围，作用在相位上
    steering_error = exp(
        steering_idx * (
            1j * 2 * pi / satellite.wavelength  # 相位因子，基于波长和天线间距
            * satellite.antenna_distance  # 天线间距
            * satellite.rng.uniform(low=error_model_config.uniform_error_interval['low'],  # 随机生成的误差下限
                                    high=error_model_config.uniform_error_interval['high'],  # 随机生成的误差上限
                                    size=(len(users), 1))  # 为每个用户生成一个误差向量
        )
    )

    # 计算误差信道状态，将误差乘到原始的信道状态信息上
    erroneous_channel_state_to_users = satellite.channel_state_to_users * steering_error

    return erroneous_channel_state_to_users  # 返回带有误差的信道状态信息
